package org.jdemo.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class SqlUtil {
    private static final String LINE_SEPARATOR = System.getProperty("line.separator", "\n");
    private static final String DEFAULT_DELIMITER = ";";

    /**
     * 执行sql脚本
     * @param conn
     * @param resource
     * @param isFullScript
     */
    public static void runScript(Connection conn, String resource, boolean isFullScript) {
        InputStreamReader reader = new InputStreamReader(SqlUtil.class.getResourceAsStream(resource));
        if(isFullScript) {
            executeFullScript(conn, reader);
        }else {
            executeLineByLine(conn, reader);
        }
    }

    /**
     * 执行完整sql脚本
     *
     * @param conn
     * @param reader
     */
    private static void executeFullScript(Connection conn, Reader reader) {
        StringBuilder script = new StringBuilder();
        try {
            BufferedReader lineReader = new BufferedReader(reader);
            String line;
            while ((line = lineReader.readLine()) != null) {
                script.append(line);
                script.append(LINE_SEPARATOR);
            }
            executeStatement(conn, script.toString());
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 一行一行执行sql脚本
     *
     * @param conn
     * @param reader
     */
    private static void executeLineByLine(Connection conn, Reader reader) {
        StringBuilder command = new StringBuilder();
        try {
            BufferedReader lineReader = new BufferedReader(reader);
            String line;
            while ((line = lineReader.readLine()) != null) {
                command = handleLine(conn, command, line);
            }
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理一行sql脚本
     *
     * @param conn
     * @param command
     * @param line
     * @return
     */
    private static StringBuilder handleLine(Connection conn, StringBuilder command, String line) {
        String trimmedLine = line.trim();
        if (lineIsComment(trimmedLine)) {
            //do nothing for comment
        } else if (commandReadyToExecute(trimmedLine)) {
            command.append(line.substring(0, line.lastIndexOf(DEFAULT_DELIMITER)));
            command.append(LINE_SEPARATOR);
            executeStatement(conn, command.toString());
            command.setLength(0);
        } else {
            command.append(line);
            command.append(LINE_SEPARATOR);
        }
        return command;
    }

    /**
     * 执行sql命令
     *
     * @param conn
     * @param command
     */
    private static void executeStatement(Connection conn, String command) {
        Statement stat = null;
        try {
            stat = conn.createStatement();
            stat.execute(command);
            stat.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断当前行是否注释
     *
     * @param trimmedLine 当前行
     * @return
     */
    private static boolean lineIsComment(String trimmedLine) {
        return trimmedLine.startsWith("//") || trimmedLine.startsWith("--");
    }

    /**
     * 判断是否是一段sql的结束，通过分号来判断
     *
     * @param trimmedLine
     * @return
     */
    private static boolean commandReadyToExecute(String trimmedLine) {
        return trimmedLine.contains(";");
    }
}
